home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / 8n1 / 8n1.s < prev    next >
Text File  |  1995-08-10  |  87KB  |  1,856 lines

  1. **  $Revision Header Start *****************************************************
  2. **                                                                            **
  3. **  Name       : 8n1.s                                                        **
  4. **  Copyright  : © Copyright 95                                               **
  5. **  Author     : L.Lucius                                                     **
  6. **  Created    : 10 Jul 95                                                    **
  7. **  Version    : 37.10                                                        **
  8. **  Translator : snma 1.99g 08-Aug-95                                         **
  9. **                                                                            **
  10. **  Date       Version  Comment                                               **
  11. **  ---------  -------  ----------------------------------------------------  **
  12. **  10 Aug 95  37.10    Added storage arbitration code to cmd_Read and        **
  13. **                      sdcmd_SetParams.                                      **
  14. **  09 Aug 95  37.10    Removed CIAF_PRTRSEL from PRTMASK to allow usage of   **
  15. **                      ring indicator line.                                  **
  16. **  06 Aug 95  37.10    Added "E-" to SNMAOPT line to prevent "Xref in        **
  17. **                      executable" message.                                  **
  18. **  06 Aug 95  37.10    Changed "8n1Base" to "Base8n1" to make more           **
  19. **                      compatible with other assemblers.                     **
  20. **  06 Aug 95  37.10    Removed ".w" from BTST instructions.                  **
  21. **  06 Aug 95  37.10    Corrected long word test of byte sized field.         **
  22. **  04 Aug 95  37.9     First Aminet Release!                                 **
  23. **  04 Aug 95  37.9     Removed some testing code and prevented unnecessary   **
  24. **                      RTS line updates.                                     **
  25. **  02 Aug 95  37.8     Added the ability to send BREAKs.  Requested by:      **
  26. **                      Dwight Zenzano                                        **
  27. **  29 Jul 95  37.7     Rearranged device init data to allow proper display   **
  28. **                      by VERSION command.  (The device base init data had   **
  29. **                      to be within the checksummed area.)                   **
  30. **  28 Jul 95  37.6     When device was opened multiple times in shared       **
  31. **                      mode, GURU occured on first close.                    **
  32. **  22 Jul 95  37.5     Corrected version number.  8n1.i was not being        **
  33. **                      generated correctly.                                  **
  34. **  22 Jul 95  37.5     Incorrect handling of interrupts caused TBE           **
  35. **                      interrupts to be missed.                              **
  36. **  13 Jul 95  37.4     Rewrote the CMD_WRITE and TBE interrupt routines.     **
  37. **                      Lengths of -1 were not being handled properly.        **
  38. **  13 Jul 95  37.3     Rewrote OpenDevice() and CloseDevice() calls to       **
  39. **                      correct several problems.                             **
  40. **  11 Jul 95  37.2     Added "no handshaking" support.  Requested by:        **
  41. **                      Ronald van Eijck                                      **
  42. **  11 Jul 95  37.1     Rewrote the RBF interrupt routines and offloaded      **
  43. **                      some of the work to a PORTS interrupt to prevent      **
  44. **                      overruns and add the EOFMODE option.                  **
  45. **  07 Jul 95  37.0     Only tried to remove the 'serial.device' instead of   **
  46. **                      removing the CURRENT owner of the serial resources.   **
  47. **                      Reported by: George Kourkoutas                        **
  48. **  06 Jul 95  37.0     Invalid size used for GetPrefs() call causing stack   **
  49. **                      overlay.  Reported by: Paul Harrison                  **
  50. **  04 Jul 95  37.0     Set defaults during OpenDevice() instead of assuming  **
  51. **                      values in I/O request are correct.  Reported by:      **
  52. **                      Koen Peetermans                                       **
  53. **  04 Jul 95  37.0     Initial Version                                       **
  54. **                                                                            **
  55. **  $Revision Header End *******************************************************
  56.          ;
  57.          ;
  58.          ;
  59.          CPU      M68010
  60.          SNMAOPT  Q,P,A,M,T,E-
  61.          ;
  62.          ;
  63.          ;
  64. DEBUG    SET       0
  65.          ;
  66.          ;
  67.          ;
  68.          SECTION  text,CODE
  69.          ;
  70.          ;
  71.          ;
  72. DEVICES_SERIAL_I_OBSOLETE  EQU      1
  73.          ;
  74.          ;
  75.          ;
  76.          INCDIR   "include:"
  77.          INCLUDE  "exec/lists.i"
  78.          INCLUDE  "exec/memory.i"
  79.          INCLUDE  "exec/resident.i"
  80.          INCLUDE  "exec/devices.i"
  81.          INCLUDE  "exec/execbase.i"
  82.          INCLUDE  "exec/io.i"
  83.          INCLUDE  "exec/ports.i"
  84.          INCLUDE  "exec/errors.i"
  85.          INCLUDE  "exec/initializers.i"
  86.          INCLUDE  "intuition/preferences.i"
  87.          INCLUDE  "devices/timer.i"
  88.          INCLUDE  "devices/serial.i"
  89.          INCLUDE  "hardware/custom.i"
  90.          INCLUDE  "hardware/cia.i"
  91.          INCLUDE  "hardware/intbits.i"
  92.          INCLUDE  "hardware/adkbits.i"
  93.          INCLUDE  "resources/misc.i"
  94.          INCLUDE  "exec/alerts.i"
  95.          INCLUDE  "exec/macros.i"
  96.          INCLUDE  "8n1.i"
  97.          ;
  98.          ;        Define hardware references
  99.          ;
  100.          XREF     _AbsExecBase
  101.          XREF     _custom
  102.          XREF     _intena,_intenar,_intreq,_intreqr
  103.          XREF     _ciab,_ciabpra
  104.          XREF     _serper,_serdat,_serdatr
  105.          XREF     _adkcon,_adkconr
  106.          ;
  107.          ;        Exec Functions
  108.          ;
  109.          XREF     _LVORemDevice,_LVOOpenDevice,_LVOCloseDevice
  110.          XREF     _LVOSupervisor
  111.          XREF     _LVORemove,_LVORemHead,_LVOAddTail
  112.          XREF     _LVOAllocMem,_LVOFreeMem,_LVOCopyMem
  113.          XREF     _LVOReplyMsg
  114.          XREF     _LVOSendIO,_LVOAbortIO
  115.          XREF     _LVODisable,_LVOEnable
  116.          XREF     _LVOFindName
  117.          XREF     _LVOOpenResource
  118.          XREF     _LVOAddIntServer,_LVORemIntServer
  119.          XREF     _LVOSetIntVector
  120.          XREF     _LVOAlert
  121.          XREF     _LVOOldOpenLibrary,_LVOCloseLibrary
  122.          ;
  123.          ;        Misc Resource Functions
  124.          ;
  125.          XREF     _LVOAllocMiscResource,_LVOFreeMiscResource
  126.          ;
  127.          ;        Intuition Functions
  128.          ;
  129.          XREF     _LVOGetPrefs
  130.          ;
  131.          ;        Mask used to get rid of the printer bits.  Remove CIAF_PRTRSEL
  132.          ;        to enable RI.
  133.          ;
  134. PRTMASK  EQU      (CIAF_PRTRPOUT|CIAF_PRTRBUSY)
  135.          ;
  136.          ;        Autovector offsets
  137.          ;
  138. LVL1VEC  EQU      (1-1)*4+$64
  139. LVL5VEC  EQU      (5-1)*4+$64
  140.          ;
  141.          ;        Device base
  142.          ;
  143.          STRUCTURE Base8n1,LIB_SIZE
  144.          UBYTE    vb_SaveDDRA
  145.          UBYTE    vb_SavePRA
  146.          APTR     vb_MiscBase
  147.          APTR     vb_OldLevel1
  148.          APTR     vb_OldLevel5
  149.          ULONG    vb_SegList
  150.          ULONG    vb_DefBaud
  151.          ULONG    vb_DefRBufLen
  152.          ULONG    vb_IntRBuf
  153.          ULONG    vb_IntRBufLen
  154.          ULONG    vb_IntBaud
  155.          UBYTE    vb_SerFlags
  156.          UBYTE    vb_Initialized
  157.          LABEL    sizeof_Base8n1
  158.          ;
  159.          ;
  160.          ;
  161. DISABLE  MACRO
  162.          jsr      _LVODisable(a6)
  163.          ENDM
  164.          ;
  165. ENABLE   MACRO
  166.          jsr      _LVOEnable(a6)
  167.          ENDM
  168.          ;
  169.          ;
  170.          ;
  171. PUTDEBUG macro    ;[level,msg]
  172. ;         ifge     DEBUG-\1
  173.          movem.l  a0/a1/d0/d1,-(sp)
  174.          lea      (.msg\@,pc),a0  ;Point to static format string
  175.          lea      (4*4,sp),a1     ;Point to args
  176.          XREF     DPutFmt
  177.          bsr      DPutFmt
  178.          movem.l  (sp)+,d0/d1/a0/a1
  179.          bra.b    .end\@
  180.  
  181. .msg\@   dc.b     \2,10,0
  182.          CNUL     0,4
  183. .end\@
  184. ;         endc
  185.          endm
  186.          ;
  187.          ;
  188.          ;
  189. DEBUG1   MACRO
  190.          IFEQ      DEBUG-1
  191.          XREF     _SendText
  192.          move.l   \2,-(sp)
  193.          pea.l    debug1s\@$
  194.          pea.l    Name
  195.          jsr      _SendText(pc)
  196.          lea.l    12(sp),sp
  197.          bra.b    debug1x\@$
  198. debug1s\@$:
  199.          dc.b     \1,0
  200.          CNOP     0,2
  201. debug1x\@$:
  202.          ENDC
  203.          ENDM
  204. DEBUG0   MACRO
  205.          XREF     _SendText
  206.          pea.l    debug1s\@$
  207.          pea.l    Name
  208.          jsr      _SendText(pc)
  209.          lea.l    8(sp),sp
  210.          bra.b    debug1x\@$
  211. debug1s\@$:
  212.          dc.b     \1,0
  213. debug1x\@$:
  214.          ENDM
  215.          ;
  216.          ;
  217.          ;
  218. Start:
  219.          moveq    #-1,d0                              ; set return code
  220.          rts                                          ; return
  221.          ;
  222.          ;        RamLib looks for this romtag
  223.          ;
  224. ROMTag   DC.W     RTC_MATCHWORD                       ; RT_MATCHWORD
  225.          DC.L     ROMTag                              ; RT_MATCHTAG
  226.          DC.L     ENDTag                              ; RT_ENDSKIP
  227.          DC.B     RTF_AUTOINIT                        ; RT_FLAGS
  228.          DC.B     VERSION                             ; RT_VERSION
  229.          DC.B     NT_DEVICE                           ; RT_TYPE
  230.          DC.B     0                                   ; RT_PRI
  231.          DC.L     Name                                ; RT_NAME
  232.          DC.L     IdString                            ; RT_IDSTRING
  233.          DC.L     Init                                ; RT_INIT
  234.          ;
  235.          ;        Perform device initialization
  236.          ;
  237. InitRoutine:
  238.          exg      d0,a0                               ; swap seglist and base
  239.          move.l   d0,vb_SegList(a0)                   ; store seglist in base
  240.          move.l   a6,SysBase                          ; store in global storage
  241.          exg      a0,d0                               ; swap them back
  242.          rts                                          ; return
  243.          ;
  244.          ;
  245.          ;
  246. dev_Open:
  247.  
  248.          DEBUG1   "Devstart %lx",#Start
  249.          move.l   a5,-(sp)                            ; save registers
  250.          movea.l  a6,a5                               ; save base
  251.          movea.l  SysBase(pc),a6                      ; get ExecBase
  252.          ;
  253.          tst.l    d0                                  ; unit 0 specified?
  254.          bne      50$                                 ; nope, error (who cares?)
  255.          ;
  256.          tst.w    LIB_OPENCNT(a5)                     ; currently open?
  257.          bne.b    10$                                 ; yep, go process
  258.          ;
  259.          move.b   IO_SERFLAGS(a1),vb_SerFlags(a5)     ; save flags
  260.          ;
  261.          tst.b    vb_Initialized(a5)                  ; already initialized?
  262.          bne.b    40$                                 ; yep, skip initialization
  263.          ;
  264.          bsr      initResources                       ; go alloc resources
  265.          tst.l    d0                                  ; initialized?
  266.          bne.b    50$                                 ; nope, error
  267.          ;
  268.          bra.b    40$                                 ; go exit
  269.          ;
  270. 10$      moveq    #SerErr_DevBusy,d0                  ; preset error status
  271.          btst.b   #SERB_SHARED,vb_SerFlags(a5)        ; opened shared?
  272.          beq.b    50$                                 ; nope, error
  273.          btst.b   #SERB_SHARED,IO_SERFLAGS(a1)        ; requesting shared?
  274.          beq.b    50$                                 ; nope, error
  275.          ;
  276.          ;        Initialize I/O request
  277.          ;
  278. 40$      moveq    #8,d0                               ; get char size
  279.          move.b   d0,IO_READLEN(a1)                   ; set read length
  280.          move.b   d0,IO_WRITELEN(a1)                  ; set write length
  281.          moveq    #1,d0                               ; get stop bits
  282.          move.b   d0,IO_STOPBITS(a1)                  ; set stop bits
  283.          move.l   vb_DefBaud(a5),IO_BAUD(a1)          ; set baud
  284.          move.l   vb_DefRBufLen(a5),IO_RBUFLEN(a1)    ; set read buffer length
  285.          ;
  286.          addq.w   #1,LIB_OPENCNT(a5)                  ; incr open count
  287.          bclr.b   #LIBB_DELEXP,LIB_FLAGS(a5)          ; clear expunge bit
  288.          moveq    #0,d0                               ; no error
  289.          ;
  290. 50$      move.b   d0,IO_ERROR(a1)                     ; store error code
  291.          movea.l  a5,a6                               ; restore base
  292.          move.l   (sp)+,a5                            ; restore registers
  293.          rts                                          ; return
  294.          ;
  295.          ;        Attempt to allocate one of the serial resources.
  296.          ;
  297. allocResource:
  298.          move.l   a6,-(sp)                            ; save base pointer
  299.          move.l   d0,-(sp)                            ; save unit
  300.          lea.l    Name(pc),a1                         ; get lock name
  301.          move.l   vb_MiscBase(a5),a6                  ; get MiscBase
  302.          jsr      _LVOAllocMiscResource(a6)           ; go allocate it
  303.          tst.l    d0                                  ; did we get it?
  304.          beq.b    20$                                 ; yep, branch
  305.          ;
  306.          ;        It's in use, so we try to locate the device using the string
  307.          ;        returned and attempt to remove it.
  308.          ;
  309.          movea.l  SysBase(pc),a6                      ; get ExecBase
  310.          ;
  311.          movea.l  d0,a1                               ; get ptr to serial name
  312.          lea.l    DeviceList(a6),a0                   ; get ptr to device list
  313.          jsr      _LVOFindName(a6)                    ; go find it
  314.          tst.l    d0                                  ; found?
  315.          beq.b    10$                                 ; nope, branch
  316.          ;
  317.          movea.l  d0,a1                               ; xfer device ptr
  318.          jsr      _LVORemDevice(a6)                   ; remove it
  319.          ;
  320.          ;        We then retry the allocate.
  321.          ;
  322. 10$      move.l   (sp),d0                             ; get unit
  323.          lea.l    Name(pc),a1                         ; get lock name
  324.          movea.l  vb_MiscBase(a5),a6                  ; get MiscBase
  325.          jsr      _LVOAllocMiscResource(a6)           ; go allocate it
  326.          ;
  327. 20$      addq.l   #4,sp                               ; restore stack ptr
  328.          movea.l  (sp)+,a6                            ; restore base ptr
  329.          rts                                          ; return
  330.          ;
  331.          ;
  332.          ;
  333. initResources:
  334.          move.l   a1,-(sp)                            ; save register
  335.          ;
  336.          lea.l    miscresource(pc),a1                 ; ptr to resource name
  337.          jsr      _LVOOpenResource(a6)                ; go open it
  338.          move.l   d0,vb_MiscBase(a5)                  ; save base
  339.          ;
  340.          moveq    #MR_SERIALPORT,d0                   ; set unit number
  341.          bsr.b    allocResource                       ; go allocate it
  342.          tst.l    d0                                  ; did we get it?
  343.          bne.b    20$                                 ; nope, error
  344.          ;
  345.          moveq    #MR_SERIALBITS,d0                   ; set unit number
  346.          bsr.b    allocResource                       ; go allocate it
  347.          tst.l    d0                                  ; did we get it?
  348.          bne.b    10$                                 ; nope, error
  349.          ;
  350.          bsr      getPrefs                            ; get default preferences
  351.          tst.l    d0                                  ; got 'em?
  352.          beq.b    30$                                 ; yep, branch
  353.          ;
  354.          moveq    #MR_SERIALPORT,d0                   ; set unit
  355.          movea.l  vb_MiscBase(a5),a6                  ; get MiscBase
  356.          jsr      _LVOFreeMiscResource(a6)            ; release the resource
  357.          ;
  358. 10$      moveq    #MR_SERIALPORT,d0                   ; set unit
  359.          movea.l  vb_MiscBase(a5),a6                  ; get MiscBase
  360.          jsr      _LVOFreeMiscResource(a6)            ; release the resource
  361.          movea.l  SysBase(pc),a6                      ; restore ExecBase
  362.          ;
  363. 20$      moveq    #SerErr_DevBusy,d0                  ; set error status
  364.          bra      40$                                 ; go return
  365.          ;
  366. 30$      moveq    #0,d1                               ; clear flags
  367.          moveq    #UNIT_VBLANK,d0                     ; set unit
  368.          lea.l    timerReq(pc),a1                     ; ptr to timer request
  369.          lea.l    timerdevice(pc),a0                  ; ptr to device name
  370.          jsr      _LVOOpenDevice(a6)                  ; go open it
  371.          ;
  372.          DISABLE                                      ; disable interrupts
  373.          ;
  374.          lea.l    _ciab,a1                            ; get ptr to ciab
  375.          move.b   ciaddra(a1),vb_SaveDDRA(a5)         ; save DDR value
  376.          andi.b   #PRTMASK,ciaddra(a1)                ; make serial bits input
  377.          move.b   ciapra(a1),vb_SavePRA(a5)           ; save PR value
  378.          ori.b    #CIAF_COMDTR|CIAF_COMRTS,ciaddra(a1) ; make DTR/RTS output
  379.          andi.b   #CIAF_COMCTS|CIAF_COMDSR|PRTMASK,ciapra(a1) ; make CTS/DSR input
  380.          andi.b   #CIAF_COMDTR|CIAF_COMRTS|PRTMASK,ciaddra(a1) ; turn on DTR/RTS
  381.          ;
  382.          moveq    #INTB_PORTS,d0                      ; get interrupt number
  383.          lea.l    VBInterrupt(pc),a1                  ; get interrupt ptr
  384.          jsr      _LVOAddIntServer(a6)                ; add it to the list
  385.          ;
  386.          bsr      getVBR                              ; get vector base (in A0)
  387.          ;
  388.          move.l   LVL1VEC(a0),vb_OldLevel1(a5)        ; save original vector
  389.          lea.l    level1(pc),a1                       ; get new vector ptr
  390.          move.l   a1,LVL1VEC(a0)                      ; set new vector
  391.          ;
  392.          move.l   LVL5VEC(a0),vb_OldLevel5(a5)        ; save original vector
  393.          lea.l    level5(pc),a1                       ; get new vector ptr
  394.          move.l   a1,LVL5VEC(a0)                      ; set new vector
  395.          ;
  396.          lea.l    _custom,a1                          ; get ptr to custom chips
  397.          move.w   #INTF_RBF|INTF_TBE,intreq(a1)       ; clear pending interrupts
  398.          move.w   #INTF_SETCLR|INTF_RBF|INTF_TBE,intena(a1) ; enable RBF & TBE
  399.          ;
  400.          addq.b   #1,vb_Initialized(a5)               ; set flag
  401.          moveq    #0,d0                               ; set good status
  402.          ;
  403.          ENABLE                                       ; enable interrupts
  404.          ;
  405. 40$      movea.l  (sp)+,a1                            ; restore register
  406.          rts                                          ; return
  407.          ;
  408.          ;        Get system preferences
  409.          ;
  410. getPrefs:
  411.          move.l   a1,-(sp)                            ; save registers
  412.          ;
  413.          lea.l    intuitlib(pc),a1                    ; ptr to library name
  414.          jsr      _LVOOldOpenLibrary(a6)              ; go open it (any version)
  415.          movea.l  d0,a6                               ; get intuition base
  416.          ;
  417.          move.l   #(pf_SerParShk+3)&$fffffffc,d0      ; size we need (aligned)
  418.          suba.l   d0,sp                               ; reserve space
  419.          ;
  420.          movea.l  sp,a0                               ; set data area ptr
  421.          jsr      _LVOGetPrefs(a6)                    ; get preferences
  422.          ;
  423.          movea.l  a6,a1                               ; get intuition base
  424.          movea.l  SysBase(pc),a6                      ; restore ExecBase
  425.          jsr      _LVOCloseLibrary(a6)                ; close it
  426.          ;
  427.          moveq    #$0f,d1                             ; set mask
  428.          and.b    pf_SerStopBuf(sp),d1                ; get bufsize index
  429.          addq.l   #8,d1                               ; calc shift value
  430.          moveq    #2,d0                               ; get 1<<1
  431.          lsl.l    d1,d0                               ; get default bufsize
  432.          move.l   d0,vb_DefRBufLen(a5)                ; and store
  433.          ;
  434.          moveq    #0,d1                               ; clear upper half
  435.          move.w   pf_BaudRate(sp),d1                  ; get baud rate
  436.          add.l    d1,d1                               ; generate offset
  437.          move.w   baudTable(pc,d1.w),d1               ; get default baud
  438.          move.l   d1,vb_DefBaud(a5)                   ; and store
  439.          ;
  440.          bsr      internalReset                       ; go init baud and buffer
  441.          ;
  442.          lea.l    (pf_SerParShk+3)&$fffffffc(sp),sp   ; restore stack
  443.          movea.l  (sp)+,a1                            ; restore registers
  444.          rts                                          ; return ( status in D0 )
  445.          ;
  446.          ;        Preferences baud lookup table
  447.          ;
  448. baudTable:
  449.          dc.w     112,300,1200,2400,4800,9600,19200,31250
  450.          ;
  451.          ;        Set exception vectors
  452.          ;
  453. getVBR:
  454.          move.l   a5,-(sp)                            ; save registers
  455.          suba.l   a0,a0                               ; ptr to vector base (68000)
  456.          btst.b   #AFB_68010,AttnFlags+1(a6)          ; 68010 or higher?
  457.          beq.b    10$                                 ; nope, go set vector
  458.          lea.l    20$(pc),a5                          ; ptr to routine
  459.          jsr      _LVOSupervisor(a6)                  ; get into supervisor state
  460. 10$      movea.l  (sp)+,a5                            ; restore register
  461.          rts                                          ; return
  462. 20$      movec.l  vbr,a0                              ; get vector base
  463.          rte                                          ; return
  464.          ;
  465.          ;
  466.          ;
  467. freeResources:
  468.          move.l   a1,-(sp)                            ; save registers
  469.          ;
  470.          DISABLE                                      ; disable interrupts
  471.          ;
  472.          bsr      getVBR                              ; get vector base (in A0)
  473.          ;
  474.          moveq    #1,d0                               ; set not restored code
  475.          ;
  476.          lea.l    level1(pc),a1                       ; get our vector ptr
  477.          cmpa.l   LVL1VEC(a0),a1                      ; do they match?
  478.          bne      10$                                 ; nope, can't restore
  479.          ;
  480.          lea.l    level5(pc),a1                       ; get our vector ptr
  481.          cmpa.l   LVL5VEC(a0),a1                      ; do they match?
  482.          bne      10$                                 ; nope, can't restore
  483.          ;
  484.          move.l   vb_OldLevel1(a5),LVL1VEC(a0)        ; restore original vector
  485.          move.l   vb_OldLevel5(a5),LVL5VEC(a0)        ; restore original vector
  486.          ;
  487.          moveq    #INTB_PORTS,d0                      ; get interrupt number
  488.          lea.l    VBInterrupt(pc),a1                  ; get interrupt ptr
  489.          jsr      _LVORemIntServer(a6)                ; remove it from the list
  490.          ;
  491.          move.w   #INTF_RBF|INTF_TBE,d0               ; indicate serial interrupts
  492.          move.w   d0,_intena                          ; disable interrupts
  493.          move.w   d0,_intreq                          ; clear pending interrupts
  494.          ;
  495.          bsr      freeBuf                             ; free allocated buffers
  496.          ;
  497.          lea.l    _ciab,a0                            ; get pointer to ciab
  498.          move.b   ciaddra(a0),d0                      ; get DDR value
  499.          andi.b   #PRTMASK,d0                         ; save printer bits
  500.          ori.b    #~PRTMASK,d0                        ; set serial bits to output
  501.          move.b   d0,ciaddra(a0)                      ; store value
  502.          ;
  503.          move.b   ciapra(a0),d0                       ; get PR value
  504.          andi.b   #PRTMASK,d0                         ; mask out serial bits
  505.          move.b   vb_SavePRA(a5),d1                   ; get saved value
  506.          andi.b   #~PRTMASK,d1                        ; mask out printer bits
  507.          or.b     d1,d0                               ; combine the two
  508.          move.b   d0,ciapra(a0)                       ; and store
  509.          ;
  510.          move.b   ciaddra(a0),d0                      ; get DDR value
  511.          andi.b   #PRTMASK,d0                         ; mask out serial bits
  512.          move.b   vb_SaveDDRA(a5),d1                  ; get saved value
  513.          andi.b   #~PRTMASK,d1                        ; mask out printer bits
  514.          or.b     d1,d0                               ; combine the two
  515.          move.b   d0,ciaddra(a0)                      ; and store
  516.          ;
  517.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  518.          jsr      _LVOCloseDevice(a6)                 ; go close it
  519.          ;
  520.          movea.l  vb_MiscBase(a5),a6                  ; get MiscBase
  521.          moveq    #MR_SERIALBITS,d0                   ; set unit
  522.          jsr      _LVOFreeMiscResource(a6)            ; release the resource
  523.          ;
  524.          moveq    #MR_SERIALPORT,d0                   ; set unit
  525.          jsr      _LVOFreeMiscResource(a6)            ; release the resource
  526.          movea.l  SysBase(pc),a6                      ; restore ExecBase
  527.          ;
  528.          ENABLE                                       ; enable interrupts
  529.          ;
  530.          subq.b   #1,vb_Initialized(a5)               ; clear flag
  531.          moveq    #0,d0                               ; free up everything
  532.          ;
  533. 10$      movea.l  (sp)+,a1                            ; restore registers
  534.          rts                                          ; return
  535.          ;
  536.          ;        Device Close routine
  537.          ;
  538. dev_Close:
  539.          ;
  540.          moveq    #-1,d0                              ; invalidate
  541.          move.l   d0,IO_DEVICE(a1)                    ;   device
  542.          ;
  543.          subq.w   #1,LIB_OPENCNT(a6)                  ; decr open count
  544.          bne.b    dev_Null                            ; still open? yep, branch
  545.          ;
  546.          move.l   a5,-(sp)                            ; save registers
  547.          movea.l  a6,a5                               ; save base
  548.          movea.l  SysBase(pc),a6                      ; get ExecBase
  549.          ;
  550.          bsr      freeResources                       ; free allocated resources
  551.          ;
  552.          movea.l  a5,a6                               ; restore base
  553.          movea.l  (sp)+,a5                            ; restore registers
  554.          ;
  555.          tst.l    d0                                  ; freed?
  556.          bne.b    dev_Null                            ; nope, can't expunge, exit
  557.          ;
  558.          clr.b    vb_SerFlags(a6)                     ; clear flags
  559.          ;
  560.          btst.b   #LIBB_DELEXP,LIB_FLAGS(a6)          ; delayed expunge set?
  561.          beq.b    dev_Null                            ; nope, go exit
  562.          ;
  563.          ;        Device Expunge routine (also fall through from dev_Close)
  564.          ;
  565. dev_Expunge:
  566.          bset.b   #LIBB_DELEXP,LIB_FLAGS(a6)          ; Set expunge flag
  567.          tst.w    LIB_OPENCNT(a6)                     ; currently open?
  568.          bne.b    dev_Null                            ; yep, so just exit
  569.          ;
  570.          move.l   vb_SegList(a6),d0                   ; get seglist ptr
  571.          movem.l  d0/a5/a6,-(sp)                      ; save registers (save D0!)
  572.          ;
  573.          movea.l  a6,a5                               ; save base
  574.          movea.l  SysBase(pc),a6                      ; get ExecBase
  575.          movea.l  a5,a1                               ; get base
  576.          jsr      _LVORemove(a6)                      ; Remove it
  577.          ;
  578.          movea.l  a5,a1                               ; get base
  579.          moveq    #0,d0                               ; clear work
  580.          move.w   LIB_NEGSIZE(a5),d0                  ; calculate
  581.          suba.w   d0,a1                               ;   memory address
  582.          add.w    LIB_POSSIZE(a5),d0                  ;     and size
  583.          jsr      _LVOFreeMem(a6)                     ; free it
  584.          ;
  585.          movem.l  (sp)+,d0/a5/a6                      ; restore registers
  586.          rts                                          ; return (seglist in D0!)
  587.          ;
  588.          ;        Device "ExtFunc" routine
  589.          ;
  590. dev_Null:
  591.          moveq    #0,d0                               ; set return code
  592.          rts                                          ; return
  593.          ;
  594.          ;
  595.          ;
  596.          IFEQ     DEBUG-1
  597. printIO:
  598.          move.l   a1,-(sp)
  599.          move.l   a0,-(sp)
  600.          pea.l    0$
  601.          pea.l    Name
  602.          jsr      _SendText(pc)
  603.          lea.l    16(sp),sp
  604.  
  605.          moveq    #0,d0
  606.          move.w   IO_COMMAND(a1),d0
  607.          move.l   d0,-(sp)
  608.          move.l   MN_REPLYPORT(a1),-(sp)
  609.          moveq    #0,d0
  610.          move.b   LN_TYPE(a1),d0
  611.          move.l   d0,-(sp)
  612.          pea.l    1$
  613.          pea.l    Name
  614.          jsr      _SendText(pc)
  615.          lea.l    20(sp),sp
  616.  
  617.          move.l   IO_LENGTH(a1),-(sp)
  618.          moveq    #0,d0
  619.          move.b   IO_ERROR(a1),d0
  620.          move.l   d0,-(sp)
  621.          move.b   IO_FLAGS(a1),d0
  622.          move.l   d0,-(sp)
  623.          pea.l    2$
  624.          pea.l    Name
  625.          jsr      _SendText(pc)
  626.          lea.l    20(sp),sp
  627.  
  628.          move.l   IO_EXTFLAGS(a1),-(sp)
  629.          move.l   IO_RBUFLEN(a1),-(sp)
  630.          move.l   IO_ACTUAL(a1),-(sp)
  631.          pea.l    3$
  632.          pea.l    Name
  633.          jsr      _SendText(pc)
  634.          lea.l    20(sp),sp
  635.  
  636.          moveq    #0,d0
  637.          move.b   IO_WRITELEN(a1),d0
  638.          move.l   d0,-(sp)
  639.          move.b   IO_READLEN(a1),d0
  640.          move.l   d0,-(sp)
  641.          move.l   IO_BAUD(a1),-(sp)
  642.          pea.l    4$
  643.          pea.l    Name
  644.          jsr      _SendText(pc)
  645.          lea.l    20(sp),sp
  646.  
  647.          moveq    #0,d0
  648.          move.w   IO_STATUS(a1),d0
  649.          move.l   d0,-(sp)
  650.          moveq    #0,d0
  651.          move.b   IO_SERFLAGS(a1),d0
  652.          move.l   d0,-(sp)
  653.          move.b   IO_STOPBITS(a1),d0
  654.          move.l   d0,-(sp)
  655.          pea.l    5$
  656.          pea.l    Name
  657.          jsr      _SendText(pc)
  658.          lea.l    20(sp),sp
  659.          rts
  660.  
  661. 0$       dc.b     '%ls - I/O     %8lx',0
  662. 1$       DC.B     'Type    %8ld     ReplyPort %8lx    Command  %8ld',0
  663. 2$       DC.B     'Flags   %8lx     Error     %8ld    Length   %8ld',0
  664. 3$       DC.B     'Actual  %8ld     RBufLen   %8ld    ExtFlags %8lx',0
  665. 4$       DC.B     'Baud    %8ld     ReadLen   %8ld    WriteLen %8ld',0
  666. 5$       DC.B     'StopBit %8ld     SerFlags  %8lx    Status   %8lx',0
  667.          ;
  668.          ;
  669.          ;
  670. abortIOs dc.b     'Abort Start',0
  671. abortIOe dc.b     'Abort End',0
  672. abortIOa dc.b     'Aborting',0
  673. beginIOs dc.b     'Begin Start',0
  674. beginIOe dc.b     'Begin End',0
  675.          CNOP     0,4
  676.          ENDC
  677. DEBUGIO  MACRO
  678.          IFEQ     DEBUG-1
  679.          lea.l    \1,a0
  680.          jsr      printIO
  681.          ENDC
  682.          ENDM
  683.          ;
  684. cmdTable dc.w     cmd_Invalid-cmdTable                ; CMD_INVALID
  685.          dc.w     cmd_Reset-cmdTable                  ; CMD_RESET
  686.          dc.w     cmd_Read-cmdTable                   ; CMD_READ
  687.          dc.w     cmd_Write-cmdTable                  ; CMD_WRITE
  688.          dc.w     cmd_Invalid-cmdTable                ; CMD_UPDATE
  689.          dc.w     cmd_Clear-cmdTable                  ; CMD_CLEAR
  690.          dc.w     cmd_Invalid-cmdTable                ; CMD_STOP
  691.          dc.w     cmd_Invalid-cmdTable                ; CMD_START
  692.          dc.w     cmd_Flush-cmdTable                  ; CMD_FLUSH
  693.          dc.w     sdcmd_Query-cmdTable                ; SDCMD_QUERY
  694.          dc.w     sdcmd_Break-cmdTable                ; SDCMD_BREAK
  695. endTable dc.w     sdcmd_SetParams-cmdTable            ; SDCMD_SETPARAMS
  696.          ;
  697.          ;        Device BeginIO routine
  698.          ;
  699. dev_BeginIO:
  700.          move.l   a5,-(sp)                            ; save register
  701.          movea.l  a6,a5                               ; save base
  702.          movea.l  SysBase(pc),a6                      ; get ExecBase
  703.          DEBUGIO  beginIOs
  704.          ;
  705.          move.b   #NT_MESSAGE,LN_TYPE(a1)             ; set type
  706.          clr.b    IO_ERROR(a1)                        ; clear error
  707.          ;
  708.          andi.b   #~(IOSERF_QUEUED|IOSERF_ACTIVE),IO_FLAGS(a1) ; clear flags
  709.          ;
  710.          move.w   IO_COMMAND(a1),d0                   ; get command
  711.          cmpi.w   #CMD_READ,d0                        ; read command?
  712.          beq.b    40$                                 ; yep, go process
  713.          cmpi.w   #CMD_WRITE,d0                       ; write command?
  714.          beq.b    50$                                 ; yep, go process
  715.          cmpi.w   #SDCMD_BREAK,d0                     ; break command?
  716.          beq.b    60$                                 ; yep, go process
  717.          add.w    d0,d0                               ; multiply by 2
  718.          cmpi.w   #endTable-cmdTable,d0               ; in range?
  719.          bhi.b    30$                                 ; nope, error
  720.          ;
  721.          move.w   cmdTable(pc,d0.w),d0                ; get routine offset
  722.          jsr      cmdTable(pc,d0.w)                   ; go do it
  723.          ;
  724. 10$      DEBUGIO  beginIOe
  725.          btst.b   #IOB_QUICK,IO_FLAGS(a1)             ; need to reply?
  726.          bne.b    20$                                 ; nope, branch
  727. 15$      jsr      _LVOReplyMsg(a6)                    ; send it back
  728.          ;
  729. 20$      movea.l  a5,a6                               ; restore base
  730.          movea.l  (sp)+,a5                            ; restore register
  731.          rts                                          ; return
  732.          ;
  733. 30$      move.b   #IOERR_NOCMD,IO_ERROR(a1)           ; invalid command
  734.          bra.b    10$                                 ; branch
  735. 40$      bsr      cmd_Read                            ; go do read
  736.          tst.l    d0                                  ; handled immediately?
  737.          beq.b    10$                                 ; yep, process quick I/O
  738.          bra.b    20$                                 ; nope, go return
  739. 50$      bsr      cmd_Write                           ; go do write
  740.          bra.b    20$                                 ; go return
  741. 60$      bsr      sdcmd_Break                         ; go do break
  742.          bra.b    20$                                 ; go return
  743.          ;
  744.          ;        Device AbortIO routine
  745.          ;
  746. dev_AbortIO:
  747.          move.l   a5,-(sp)                            ; save registers
  748.          movea.l  a6,a5                               ; save base
  749.          movea.l  SysBase(pc),a6                      ; get ExecBase
  750.          DEBUGIO  abortIOs
  751.          ;
  752.          DISABLE                                      ; disable interrupts
  753.          ;
  754.          btst.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; queued request?
  755.          bne.b    40$                                 ; yep, branch
  756.          ;
  757.          btst.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; active request?
  758.          beq.b    10$                                 ; nope, just exit
  759.          ;
  760.          cmpi.w   #CMD_READ,IO_COMMAND(a1)            ; was it a read?
  761.          beq.b    20$                                 ; yep, go process
  762.          ;
  763.          cmpi.w   #CMD_WRITE,IO_COMMAND(a1)           ; was it a write?
  764.          beq.b    30$                                 ; yep, go process
  765.          ;
  766.          cmpi.w   #SDCMD_BREAK,IO_COMMAND(a1)         ; was it a break?
  767.          beq.b    30$                                 ; yep, go process
  768.          ;
  769.          ;        Fall through or enter from below
  770.          ;
  771. 10$      ENABLE                                       ; enable ints and return
  772.          movea.l  a5,a6                               ; restore base
  773.          movea.l  (sp)+,a5                            ; restore registers
  774.          rts                                          ; return
  775.          ;
  776.          ;        Abort an active read request
  777.          ;
  778. 20$      clr.l    cr_IOReq                            ; no longer active
  779.          bra.b    50$                                 ; go set flags
  780.          ;
  781.          ;        Abort an active write request
  782.          ;
  783. 30$      clr.l    cw_Length                           ; no longer active
  784.          clr.l    cw_IOReq                            ; no longer active
  785.          move.l   cw_Buffer(pc),d0                    ; get buffer ptr
  786.          sub.l    IO_DATA(a1),d0                      ; calc number of bytes xfer'd
  787.          move.l   d0,IO_ACTUAL(a1)                    ; store
  788.          ;
  789.          ;        Force a TBE interrupt to get the next write going.
  790.          ;
  791.          move.w   #INTF_SETCLR|INTF_TBE,_intreq       ; make TBE pending
  792.          bra.b    50$                                 ; go set flags
  793.          ;
  794.          ;        Remove I/O from queue.
  795.          ;
  796. 40$      move.l   a1,-(sp)                            ; save ptr
  797.          jsr      _LVORemove(a6)                      ; remove it
  798.          movea.l  (sp)+,a1                            ; restore ptr
  799.          ;
  800.          ;        Set error and return I/O
  801.          ;
  802. 50$      andi.b   #~(IOSERF_QUEUED|IOSERF_ACTIVE),IO_FLAGS(a1) ; clear flags
  803.          moveq    #IOERR_ABORTED,d0                   ; indicate aborted
  804.          move.b   d0,IO_ERROR(a1)                     ; store status
  805.          jsr      _LVOReplyMsg(a6)                    ; send it back
  806.          bra.b    10$                                 ; branch to return
  807.          ;
  808.          ;        Abort all active/queued commands and reset internal state
  809.          ;
  810. cmd_Reset:
  811.          move.l   a1,-(sp)                            ; save I/O request
  812.          bsr.b    cmd_Flush                           ; go abort queued requests
  813.          ;
  814.          DISABLE                                      ; disable interrupts
  815.          ;
  816.          ;        This must follow the DISABLE
  817.          ;
  818.          exg      a5,a6                               ; exchange base and ExecBase
  819.          ;
  820.          move.l   cr_IOReq(pc),d0                     ; active read?
  821.          beq.b    10$                                 ; nope, branch
  822.          movea.l  d0,a1                               ; get I/O request
  823.          bsr      dev_AbortIO                         ; go abort it
  824.          ;
  825.          ;
  826.          ;
  827. 10$      move.l   cw_IOReq(pc),d0                     ; active write?
  828.          beq.b    20$                                 ; nope, branch
  829.          movea.l  d0,a1                               ; get I/O request
  830.          bsr      dev_AbortIO                         ; go abort it
  831.          ;
  832. 20$      exg      a5,a6                               ; restore base and ExecBase
  833.          movea.l  (sp)+,a1                            ; restore I/O request
  834.          moveq    #8,d0                               ; get char size
  835.          move.b   d0,IO_READLEN(a1)                   ; set read length
  836.          move.b   d0,IO_WRITELEN(a1)                  ; set write length
  837.          moveq    #1,d0                               ; get stop bits
  838.          move.b   d0,IO_STOPBITS(a1)                  ; set stop bits
  839.          move.l   vb_DefBaud(a5),IO_BAUD(a1)          ; set to default baud
  840.          move.l   vb_DefRBufLen(a5),IO_RBUFLEN(a1)    ; set to default buflen
  841.          bsr      internalReset                       ; go set/verify parameters
  842.          move.b   d0,IO_ERROR(a1)                     ; set error code
  843.          ENABLE                                       ; enable interrupts
  844.          rts                                          ; return
  845.          ;
  846.          ;        Abort all "queued" requests, leaving all active alone.
  847.          ;
  848. cmd_Flush:
  849.          movem.l  a1/a2,-(sp)                         ; save registers
  850.          DISABLE                                      ; disable interrupts
  851.          ;
  852.          ;        Abort all queued read requests.
  853.          ;
  854.          lea.l    readQ(pc),a2                        ; get ptr to read queue
  855.          bsr.b    20$                                 ; branch to abort
  856.          ;
  857.          ;        Abort all queued write requests.
  858.          ;
  859.          lea.l    writeQ(pc),a2                       ; get ptr to write queue
  860.          bsr.b    20$                                 ; branch to abort
  861.          ;
  862.          ;        Enable, restore, and return to caller
  863.          ;
  864.          ENABLE                                       ; enable interrupts
  865.          movem.l  (sp)+,a1/a2                         ; restore registers
  866.          ;
  867.          ;        !!!NOTE!!!  In a mad attempt to save 2 bytes, this RTS is used
  868.          ;        by the subroutine below.  Why waste 'em?  B-)
  869.          ;
  870. 10$      rts                                          ; return ( used below too!! )
  871.          ;
  872.          ;        Subroutine to remove and reply each I/O request.
  873.          ;
  874. 20$      movea.l  a2,a0                               ; get list ptr
  875.          jsr      _LVORemHead(a6)                     ; get I/O request
  876.          tst.l    d0                                  ; end of list?
  877.          beq.b    10$                                 ; yep, branch to return
  878.          ;
  879.          movea.l  d0,a1                               ; get I/O request
  880.          bclr.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; no longer queued
  881.          moveq    #IOERR_ABORTED,d0                   ; indicate aborted
  882.          move.b   d0,IO_ERROR(a1)                     ; store status
  883.          ;
  884.          jsr      _LVOReplyMsg(a6)                    ; send it back
  885.          bra.b    20$                                 ; continue with next
  886.          ;
  887.          ;        Process a CMD_READ request.
  888.          ;
  889. cmd_Read:
  890.          ;
  891.          ;        Zero length requests just get returned.
  892.          ;
  893.          clr.l    IO_ACTUAL(a1)                       ; clear bytes read
  894.          move.l   IO_LENGTH(a1),d0                    ; get length and test
  895.          beq.b    20$                                 ; yep, leave
  896.          ;
  897.          ;        The disable counter works just like exec's TDNestCnt field.  It's
  898.          ;        initialized to -1.  After incrementing, if it is 0, then we
  899.          ;        can attempt to process this request immediately.  If it's > 0,
  900.          ;        then we're already disabled and we must queue this request.
  901.          ;
  902.          addq.b   #1,disableRead                      ; incr disable count
  903.          bgt.b    50$                                 ; >0, already disabled
  904.          ;
  905.          ;        If we're already processing an request, this one has to wait
  906.          ;        until that one is done, so go queue it.
  907.          ;
  908.          move.l   cr_IOReq(pc),d1                     ; have an active request?
  909.          bne.b    50$                                 ; yep, go queue this one
  910.          ;
  911.          ;        If we don't have enough bytes to satisfy this request then go
  912.          ;        queue it.
  913.          ;
  914.          ;        NOTE:  This could be changed to a loop to copy as many bytes
  915.          ;               as possible and THEN if there's not enough to satisfy
  916.          ;               the request queue it for the remainder.  This would move
  917.          ;               some of the copying to the task level instead of at the
  918.          ;               interrupt level.  Maybe I'll try it one day.  B^)
  919.          ;
  920.          cmp.l    i_InCnt(pc),d0                      ; length > current bytes?
  921.          bgt.b    50$                                 ; yep, go queue it
  922.          ;
  923.          ;        Setup fields and go copy the data
  924.          ;
  925.          move.l   IO_DATA(a1),cr_OutPtr               ; get/set output ptr
  926.          move.l   IO_LENGTH(a1),cr_Length             ; get/set output count
  927.          bsr      copyData                            ; go copy 'em
  928.          moveq    #0,d0
  929.          ;
  930.          ;        We're done, so back off the disable counter.
  931.          ;
  932. 10$      subq.b   #1,disableRead                      ; decr disable count
  933.          ;
  934.          ;        Return to caller
  935.          ;
  936. 20$      rts                                          ; return
  937.          ;
  938.          ;        Just set flags and queue.  The read interrupt will handle it.
  939.          ;
  940. 50$      bset.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; indicate queued
  941.          bclr.b   #IOB_QUICK,IO_FLAGS(a1)             ; clear quick I/O flag
  942.          ;
  943.          ;        Add this request to the end.  List arbitration is controlled
  944.          ;        with the read disable counter.
  945.          ;
  946.          lea.l    readQ(pc),a0                        ; get pointer to read queue
  947.          move.l   a1,-(sp)                            ; save I/O request
  948.          jsr      _LVOAddTail(a6)                     ; and queue it
  949.          movea.l  (sp)+,a1                            ; restore I/O request
  950.          ;
  951.          ;        Indicate that this request was not handled immediatly.
  952.          ;
  953.          moveq    #1,d0                               ; not handled immediately
  954.          bra.b    10$                                 ; branch to return
  955.          ;
  956.          ;        Process a CMD_WRITE request.
  957.          ;
  958. cmd_Write:
  959.          ;
  960.          ;        Zero length requests just get returned.
  961.          ;
  962.          clr.l    IO_ACTUAL(a1)                       ; clear bytes written
  963.          move.l   IO_LENGTH(a1),d0                    ; have anything to write?
  964.          beq.b    wbexit                              ; nope, exit
  965.          ;
  966.          ;        Entry point for Break command and fall through from cmd_Write.
  967.          ;
  968. sdcmd_Break:
  969.          ;
  970.          ;        Just set flags and queue. The TBE interrupt will handle it.
  971.          ;
  972.          bset.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; indicate queued
  973.          bclr.b   #IOB_QUICK,IO_FLAGS(a1)             ; clear quick I/O flag
  974.          ;
  975.          ;        Protect.
  976.          ;
  977.          DISABLE                                      ; disable interrupts
  978.          ;
  979.          ;        Add request to end of queue.
  980.          ;
  981.          lea.l    writeQ(pc),a0                       ; get queue list ptr
  982.          move.l   a1,-(sp)                            ; save I/O request
  983.          jsr      _LVOAddTail(a6)                     ; and queue it
  984.          movea.l  (sp)+,a1                            ; restore I/O request
  985.          ;
  986.          ;        If we have an active request, don't force interrupt.
  987.          ;
  988.          move.l   cw_IOReq(pc),d0                     ; have an active request?
  989.          bne.b    10$                                 ; yep, branch
  990.          ;
  991.          ;        Force a TBE interrupt to get the writes going.
  992.          ;
  993.          move.w   #INTF_SETCLR|INTF_TBE,_intreq       ; make TBE pending
  994.          ;
  995.          ;        Enable and return to caller.
  996.          ;
  997. 10$      ENABLE                                       ; enable interrupts
  998. wbexit   rts                                          ; return
  999.          ;
  1000.          ;        Resets serial read buffer
  1001.          ;
  1002.          ;        Since this routine is called internally, it must NOT reference
  1003.          ;        the I/O request.
  1004.          ;
  1005. cmd_Clear
  1006.          DISABLE                                      ; disable interrupts
  1007.          ;
  1008.          ;        Load registers
  1009.          ;
  1010.          move.l   vb_IntRBuf(a5),d0                   ; get internal buffer ptr
  1011.          move.l   vb_IntRBufLen(a5),d1                ; and internal buffer len
  1012.          lea.l    i_BufPtr(pc),a0                     ; get ptr internal control
  1013.          ;
  1014.          ;        Initialize global buffer variables
  1015.          ;
  1016.          move.l   d0,(a0)+                            ; store buffer ptr
  1017.          move.l   d0,(a0)+                            ; set current input ptr
  1018.          move.l   d0,(a0)+                            ; set current output ptr
  1019.          add.l    d1,d0                               ; add buffer length
  1020.          move.l   d0,(a0)+                            ; store ptr to end of buffer
  1021.          clr.l    (a0)+                               ; clear byte cnt
  1022.          move.l   vb_IntBaud(a5),d0                   ; get internal baud
  1023.          lsr.l    #4,d0                               ; divide by 16
  1024.          sub.l    d0,d1                               ; subtract from length
  1025.          move.l   d1,(a0)                             ; set threshold
  1026.          ;
  1027.          ;        Enable and return to caller.
  1028.          ;
  1029.          ENABLE                                       ; enable interrupts
  1030.          rts                                          ; return
  1031.          ;
  1032.          ;
  1033.          ;
  1034. cmd_Invalid
  1035.          move.b   #IOERR_NOCMD,IO_ERROR(a1)           ; set bad status
  1036.          rts                                          ; return
  1037.          ;
  1038.          ;        Returns number of bytes currently in internal buffer and
  1039.          ;        current serial port status.
  1040.          ;
  1041.          ;        NOTE:  Not completely compatible with standard serial.device
  1042.          ;        since it doesn't return the upper byte of IO_STATUS.
  1043.          ;
  1044. sdcmd_Query:
  1045.          DISABLE                                      ; disable interrupts
  1046.          moveq    #0,d0                               ; clear d0
  1047.          move.b   _ciabpra,d0                         ; get PR register
  1048.          andi.w   #~PRTMASK,d0                        ; zap printer bits
  1049.          move.w   d0,IO_STATUS(a1)                    ; store status
  1050.          move.l   i_InCnt(pc),IO_ACTUAL(a1)           ; byte left in buffer
  1051.          ENABLE                                       ; restore interrupts
  1052.          rts                                          ; return
  1053.          ;
  1054.          ;
  1055.          ;
  1056. sdcmd_SetParams:
  1057.          ;
  1058.          ;        Validate the read, write, and stop bit lengths.
  1059.          ;
  1060.          moveq    #8,d0                               ; get char length
  1061.          cmp.b    IO_READLEN(a1),d0                   ; 8 bit chars for read?
  1062.          bne.b    40$                                 ; nope, branch
  1063.          cmp.b    IO_WRITELEN(a1),d0                  ; 8 bit chars for write?
  1064.          bne.b    40$                                 ; nope, branch
  1065.          moveq    #1,d0                               ; get stop bits
  1066.          cmp.b    IO_STOPBITS(a1),d0                  ; 1 stop bit?
  1067.          bne.b    40$                                 ; nope, branch
  1068.          ;
  1069.          ;        Get and validate the baud rate.
  1070.          ;
  1071.          move.l   IO_BAUD(a1),d1                      ; get baud from I/O req
  1072.          bne.b    20$                                 ; specified?
  1073.          move.l   vb_IntBaud(a5),d1                   ; get current baud from base
  1074.          bne.b    20$                                 ; specified?
  1075.          move.l   vb_DefBaud(a5),d1                   ; get default baud from base
  1076. 20$      cmpi.l   #110,d1                             ; too low?
  1077.          blt.b    40$                                 ; error
  1078.          cmpi.l   #292000,d1                          ; too high?
  1079.          bgt.b    40$                                 ; error
  1080.          ;
  1081.          ;        Get and validate the buffer length.
  1082.          ;
  1083.          move.l   IO_RBUFLEN(a1),d0                   ; get buffer length
  1084.          bne.b    30$                                 ; specified?
  1085.          move.l   vb_IntRBufLen(a5),d0                ; get current from base
  1086.          bne.b    30$                                 ; specified?
  1087.          move.l   vb_DefRBufLen(a5),d0                ; get default from base
  1088.          ;
  1089. 30$      bsr.b    internalReset                       ; go init baud and buffer
  1090. 35$      move.b   d0,IO_ERROR(a1)                     ; set error code
  1091.          bne.b    39$
  1092.          ;
  1093.          ;        If the 7wire bit is not on, we will only use 3-wire protocol
  1094.          ;
  1095.          moveq    #0,d0                               ; clear flag
  1096.          btst.b   #SERB_7WIRE,IO_SERFLAGS(a1)         ; use 7wire handshaking?
  1097.          beq.b    36$                                 ; nope, branch
  1098.          moveq    #1,d0                               ; set flag
  1099. 36$      move.b   d0,Handshake                        ; store flag
  1100.          ;
  1101.          ;        Return to caller
  1102.          ;
  1103. 39$      rts                                          ; return
  1104.          ;
  1105.          ;        Invalid parm detected.
  1106.          ;
  1107. 40$      moveq    #SerErr_InvParam,d0                 ; set error
  1108.          bra.b    35$                                 ; go return
  1109.          ;
  1110.          ;        Reset the buffer and baud rate
  1111.          ;
  1112.          ;        Registers:  D0 = Buffer length
  1113.          ;                    D1 = Baud rate
  1114.          ;
  1115. internalReset:
  1116.          ;
  1117.          ;        Disable interrupts.
  1118.          ;
  1119.          DISABLE                                      ; disable interrupts
  1120.          ;
  1121.          ;        Save buffer length and go set serper.
  1122.          ;
  1123.          move.l   d0,-(sp)                            ; save D0
  1124.          move.l   d1,d0                               ; get baud rate
  1125.          bsr.b    setPeriod                           ; go set the serper register
  1126.          move.l   (sp)+,d0                            ; restore D0
  1127.          ;
  1128.          ;        Determine if the buffer length is adequate for the selected CPS.
  1129.          ;        If not, use 64K for the length.
  1130.          ;
  1131.          move.l   vb_IntBaud(a5),d1                   ; get current baud
  1132.          lsr.l    #$3,d1                              ; divide by 8
  1133.          cmp.l    d1,d0                               ; buflen > CPS
  1134.          bhi.b    10$                                 ; yep, branch
  1135.          move.l   #65536,d0                           ; else use 64K
  1136.          ;
  1137. 10$      bsr.b    allocBuf                            ; go allocate a new buffer
  1138.          ;
  1139.          ;        Enable and return to caller.
  1140.          ;
  1141.          ENABLE                                       ; enable interrupts
  1142.          rts                                          ; return (D0 has status)
  1143.          ;
  1144.          ;        Set serial period register
  1145.          ;
  1146. setPeriod:
  1147.          cmp.l    vb_IntBaud(a5),d0                   ; current baud = new baud?
  1148.          beq.b    40$                                 ; yep, just exit
  1149.          move.l   d0,vb_IntBaud(a5)                   ; save new baud
  1150.          move.l   d0,d1                               ; save again
  1151.          lsl.l    #3,d0                               ; baud *= 8
  1152.          sub.l    d1,d0                               ; baud -= saved baud
  1153.          move.l   #25000000,d1                        ; get NTSC base
  1154.          cmpi.b   #50,PowerSupplyFrequency(a6)        ; PAL machine?
  1155.          bne.b    10$                                 ; nope, branch
  1156.          move.l   #24772416,d1                        ; get PAL base
  1157. 10$      cmpi.l   #$FFFF,d0                           ; Divide
  1158.          ble.b    20$                                 ;
  1159.          lsr.l    #5,d0                               ;
  1160.          divu.w   d0,d1                               ;
  1161.          andi.l   #$FFFF,d1                           ;
  1162.          lsr.l    #5,d1                               ;
  1163.          bra.b    30$                                 ;
  1164. 20$      divu.w   d0,d1                               ;
  1165. 30$      move.w   d1,_serper                          ; set period value
  1166. 40$      rts
  1167.          ;
  1168.          ;        Allocate new internal buffer
  1169.          ;
  1170. allocBuf:
  1171.          cmp.l    vb_IntRBufLen(a5),d0                ; len same as previous?
  1172.          beq.b    10$                                 ; yep, so no need to alloc
  1173.          move.l   d0,d1                               ; save length
  1174.          movem.l  d1/a1,-(sp)                         ; save registers
  1175.          moveq    #MEMF_PUBLIC,d1                     ; public memory
  1176.          jsr      _LVOAllocMem(a6)                    ; go allocate it
  1177.          movem.l  (sp)+,d1/a1                         ; restore registers
  1178.          tst.l    d0                                  ; did we get it?
  1179.          beq.b    20$                                 ; if zero, error
  1180.          bsr.b    freeBuf                             ; go free previous buffer
  1181.          move.l   d0,vb_IntRBuf(a5)                   ; store new ptr
  1182.          move.l   d1,vb_IntRBufLen(a5)                ; and length
  1183.          bsr      cmd_Clear                           ; go setup buffer
  1184. 10$      moveq    #0,d0                               ; success
  1185.          rts                                          ; return
  1186. 20$      moveq    #SerErr_BufErr,d0                   ; set error status
  1187.          rts                                          ; return
  1188.          ;
  1189.          ;        Free internal buffer
  1190.          ;
  1191. freeBuf:
  1192.          movem.l  d0-d1/a0-a1,-(sp)                   ; save registers
  1193.          move.l   vb_IntRBuf(a5),d0                   ; is one there?
  1194.          beq.b    10$                                 ; no so branch
  1195.          movea.l  d0,a1                               ; get ptr
  1196.          move.l   vb_IntRBufLen(a5),d0                ; get length
  1197.          clr.l    vb_IntRBuf(a5)                      ; clear
  1198.          clr.l    vb_IntRBufLen(a5)                   ; clear
  1199.          jsr      _LVOFreeMem(a6)                     ; free it
  1200. 10$      movem.l  (sp)+,d0-d1/a0-a1                   ; restore registers
  1201.          rts                                          ; return
  1202.          ;
  1203.          ;        Checks CTS status and if clear generates a TBE interrupt or
  1204.          ;        requeues the timer request.
  1205.          ;
  1206.          ;        Entered from Exec using the MsgPort callback.
  1207.          ;
  1208.          ;        Input:   a6 = ExecBase
  1209.          ;        Output:  none
  1210.          ;
  1211.          ;        No need to preserve d0/d1/a0/a1
  1212.          ;
  1213. timerRtn:
  1214.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  1215.          jsr      _LVORemove(a6)                      ; remove request
  1216.          ;
  1217.          ;        If we were breaking, reset adkcon.
  1218.          ;
  1219.          btst.b   #ADKB_UARTBRK,_adkconr              ; were we breaking?
  1220.          beq.b    10$                                 ; nope, skip reset
  1221.          ;
  1222.          move.w   #ADKF_UARTBRK,_adkcon               ; stop breaking
  1223.          ;
  1224.          ;
  1225.          ;
  1226. 10$      move.b   Handshake(pc),d0                    ; are we handshaking?
  1227.          beq.b    20$                                 ; nope, generate interrupt
  1228.          btst.b   #CIAB_COMCTS,_ciabpra               ; clear to send?
  1229.          beq.b    20$                                 ; yep, go start writing
  1230.          ;
  1231.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  1232.          move.l   #1000,IOTV_TIME+TV_MICRO(a1)        ; wait for .001 seconds
  1233.          jsr      _LVOSendIO(a6)                      ; go queue it
  1234.          bra.b    30$                                 ; branch to return
  1235.          ;
  1236.          ;        CTS is clear so generate TBE interrupt to restart writing
  1237.          ;
  1238. 20$      move.w   #INTF_SETCLR|INTF_TBE,_intreq       ; set TBE interrupt
  1239. 30$      rts                                          ; return
  1240.          ;
  1241.          ;        Non serial interrupt
  1242.          ;
  1243. level1n:
  1244.          movem.l  d0-d1/a0-a1/a5-a6,-(sp)             ; save registers
  1245.          lea      _custom,a0                          ; get ptr to custom regs
  1246.          move.w   intenar(a0),d1                      ; get enabled interrupts
  1247.          btst     #INTB_INTEN,d1                      ; interrupts enabled?
  1248.          beq.b    20$                                 ; nope, just exit
  1249.          and.w    intreqr(a0),d1                      ; and in requested interrupts
  1250.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1251.          ;
  1252.          btst     #INTB_DSKBLK,d1                     ; Disk block done?
  1253.          beq.b    10$                                 ; nope, branch
  1254.          ;
  1255.          movem.l  IVDSKBLK(a6),a1/a5                  ; get data and code ptrs
  1256.          pea.l    20$(pc)                             ; push return address
  1257.          jmp      (a5)                                ; jump to routine
  1258.          ;
  1259. 10$      btst     #INTB_SOFTINT,d1                    ; software interrupt?
  1260.          beq.b    20$                                 ; nope, branch
  1261.          ;
  1262.          movem.l  IVSOFTINT(a6),a1/a5                 ; get data and code ptrs
  1263.          pea.l    20$(pc)                             ; push return address
  1264.          jmp      (a5)                                ; jump to routine
  1265.          ;
  1266. 20$      movem.l  (sp)+,d0-d1/a0-a1/a5-a6             ; restore registers
  1267.          rte                                          ; return
  1268.          ;
  1269.          ;        Level 1 interrupt handler
  1270.          ;
  1271. level1:
  1272.          btst.b   #INTB_TBE,_intreqr+1                ; xmit buffer empty?
  1273.          beq.b    level1n                             ; nope, invoke old handler
  1274.          ;
  1275.          ;        Handle "Transmit Buffer Empty" interrupt (write)
  1276.          ;
  1277.          move.w   #INTF_TBE,_intreq                   ; clear interrupt
  1278.          move.l   d0,-(sp)                            ; save D0 (faster than MOVEM)
  1279.          move.l   a0,-(sp)                            ; save A0 (faster than MOVEM)
  1280.          ;
  1281.          ;        If we're not handshaking, bypass it.
  1282.          ;
  1283. 10$      move.b   Handshake(pc),d0                    ; are we handshaking?
  1284.          beq.b    20$                                 ; nope, skip CTS test
  1285.          btst.b   #CIAB_COMCTS,_ciabpra               ; clear to send?
  1286.          bne.b    40$                                 ; nope, branch
  1287.          ;
  1288.          ;        If cw_Length goes negative here, we are either done with a
  1289.          ;        request or we were called as a result of a fake interrupt
  1290.          ;        to force us to get the next request going.
  1291.          ;
  1292. 20$      subq.l   #1,cw_Length                        ; decr write length
  1293.          blt.b    60$                                 ; < zero, done, branch
  1294.          ;
  1295.          ;        Currently processing a request.
  1296.          ;
  1297.          movea.l  cw_Buffer(pc),a0                    ; get buffer ptr
  1298.          move.w   #256,d0                             ; set stop bit
  1299.          move.b   (a0)+,d0                            ; get next byte
  1300.          move.l   a0,cw_Buffer                        ; store buffer ptr
  1301.          move.w   d0,_serdat                          ; store in serdat reg
  1302.          ;
  1303. 30$      movea.l  (sp)+,a0                            ; restore registers
  1304.          move.l   (sp)+,d0                            ; restore registers
  1305.          rte                                          ; return
  1306.          ;
  1307.          ;        Queue a timer request to recheck CTS status
  1308.          ;
  1309. 40$      movem.l  d1/a1/a6,-(sp)                      ; save registers
  1310.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  1311.          move.l   #1000,IOTV_TIME+TV_MICRO(a1)        ; wait for .001 seconds
  1312.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1313.          jsr      _LVOSendIO(a6)                      ; queue the request
  1314.          movem.l  (sp)+,d1/a1/a6                      ; restore registers
  1315.          bra.b    30$                                 ; go return
  1316.          ;
  1317.          ;        There aren't anymore requests, so clear and exit
  1318.          ;
  1319. 50$      clr.l    cw_Length-Start(a6)                 ; clear length
  1320.          clr.l    cw_IOReq-Start(a6)                  ; clear
  1321.          movem.l  (sp)+,d1/a1/a6                      ; restore registers
  1322.          bra.b    30$                                 ; go return
  1323.          ;
  1324.          ;        Write request completed
  1325.          ;
  1326. 60$
  1327.          movem.l  d1/a1/a6,-(sp)                      ; save registers
  1328.          ;
  1329.          move.l   cw_IOReq(pc),d0                     ; active I/O request?
  1330.          beq.b    70$                                 ; nope, branch
  1331.          ;
  1332.          ;        Reply it and setup for next
  1333.          ;
  1334.          movea.l  d0,a1                               ; get I/O request
  1335.          bclr.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; no longer active
  1336.          clr.b    IO_ERROR(a1)                        ; no error
  1337.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1338.          jsr      _LVOReplyMsg(a6)                    ; return I/O request
  1339.          ;
  1340. 70$      lea.l    Start(pc),a6                        ; get section base
  1341.          ;
  1342.          lea.l    writeQ(pc),a1                       ; get ptr to write queue
  1343.          move.l   (a1),a0                             ; get head of list
  1344.          move.l   (a0),d0                             ; get successor
  1345.          beq      50$                                 ; end of list? yep, branch
  1346.          ;
  1347.          ;        Remove the node from the list
  1348.          ;
  1349.          move.l   d0,(a1)                             ; make new head
  1350.          exg.l    d0,a0                               ; swap nodes
  1351.          move.l   a1,LN_PRED(a0)                      ; store predecessor
  1352.          ;
  1353.          move.l   d0,a1                               ; get I/O request
  1354.          ;
  1355.          ;        If it's a BREAK, then branch to process as such.
  1356.          ;
  1357.          cmpi.w   #SDCMD_BREAK,IO_COMMAND(a1)         ; BREAK command?
  1358.          beq.b    100$                                ; yep, branch
  1359.          ;
  1360.          ;        Check for absolute length
  1361.          ;
  1362.          move.l   IO_DATA(a1),a0                      ; get data ptr
  1363.          moveq    #-1,d1                              ; get value
  1364.          move.l   IO_LENGTH(a1),d0                    ; get length
  1365.          cmp.l    d1,d0                               ; length = -1?
  1366.          bne.b    90$                                 ; yep, go scan
  1367.          ;
  1368.          ;        Scan the data for null to calc the length
  1369.          ;
  1370.          move.l   a0,d1                               ; save data ptr
  1371. 80$      tst.b    (a0)+                               ; does it equal 0?
  1372.          bne.b    80$                                 ; nope, so continue
  1373.          suba.l   d1,a0                               ; calc # of bytes+1
  1374.          move.l   a0,d0                               ; xfer
  1375.          subq.l   #1,d0                               ; cal # of bytes
  1376.          movea.l  d1,a0                               ; get data ptr
  1377.          ;
  1378. 90$      move.l   d0,IO_ACTUAL(a1)                    ; go ahead and set it
  1379.          bclr.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; no longer queued
  1380.          bset.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; make it active
  1381.          move.l   d0,cw_Length-Start(a6)              ; store length
  1382.          move.l   a0,cw_Buffer-Start(a6)              ; store buffer ptr
  1383.          move.l   a1,cw_IOReq-Start(a6)               ; store I/O request ptr
  1384.          ;
  1385.          movem.l  (sp)+,d1/a1/a6                      ; restore registers
  1386.          bra      10$                                 ; go start request
  1387.          ;
  1388.          ;        Start the BREAK.
  1389.          ;
  1390. 100$     bclr.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; no longer queued
  1391.          bset.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; make it active
  1392.          clr.l    cw_Length-Start(a6)                 ; clear length
  1393.          move.l   a1,cw_IOReq-Start(a6)               ; store I/O request ptr
  1394.          move.w   #ADKF_SETCLR|ADKF_UARTBRK,_adkcon   ; start break
  1395.          move.l   IO_BRKTIME(a1),d0                   ; get break time
  1396.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  1397.          move.l   d0,IOTV_TIME+TV_MICRO(a1)           ; set the timeout
  1398.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1399.          jsr      _LVOSendIO(a6)                      ; queue the request
  1400.          movem.l  (sp)+,d1/a1/a6                      ; restore registers
  1401.          bra      30$                                 ; go exit
  1402.          ;
  1403.          ;        Non serial interrupt (xfers control to old handler)
  1404.          ;
  1405. level5n:
  1406.          movem.l  d0-d1/a0-a1/a5-a6,-(sp)             ; save registers
  1407.          lea      _custom,a0                          ; get ptr to custom regs
  1408.          move.w   intenar(a0),d1                      ; get enabled interrupts
  1409.          btst     #INTB_INTEN,d1                      ; interrupts enabled?
  1410.          beq.b    10$                                 ; nope, just exit
  1411.          and.w    intreqr(a0),d1                      ; and in requested interrupts
  1412.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1413.          btst     #INTB_DSKSYNC,d1                    ; Disk synchronized?
  1414.          beq.b    10$                                 ; nope, branch
  1415.          movem.l  IVDSKSYNC(A6),a1/a5                 ; get data and code ptrs
  1416.          jsr      (a5)                                ; branch to routine
  1417. 10$      movem.l  (sp)+,d0-d1/a0-a1/a5-a6             ; restore registers
  1418.          rte                                          ; return
  1419.          ;
  1420.          ;        Default Level 5 handler (no I/O requests active)
  1421.          ;
  1422. level5:
  1423.          btst.b   #INTB_RBF,_intreqr                  ; receive buffer full?
  1424.          beq.b    level5n                             ; nope, invoke old handler
  1425.          ;
  1426.          move.l   a0,-(sp)                            ; save registers
  1427.          ;
  1428. 10$      btst.b   #7,_serdatr                         ; Overrun?
  1429.          bne.b    50$                                 ; yep, branch
  1430.          ;
  1431. 20$      movea.l  i_BufIn(pc),a0                      ; get current ptr
  1432.          move.b   _serdatr+1,(a0)+                    ; store received byte
  1433.          move.w   #INTF_RBF,_intreq                   ; clear RBF interrupt
  1434.          addq.l   #1,i_InCnt                          ; incr bytes in buffer
  1435.          ;
  1436.          cmpa.l   i_BufEnd(pc),a0                     ; hit end of buffer?
  1437.          beq.b    60$                                 ; yep, branch
  1438. 30$      move.l   a0,i_BufIn                          ; store input ptr
  1439.          ;
  1440.          subq.l   #1,i_Thresh                         ; close to full buffer?
  1441.          beq.b    70$                                 ; yep, branch
  1442.          ;
  1443. 40$      btst.b   #INTB_RBF,_intreqr                  ; receive buffer full?
  1444.          bne.b    10$                                 ; yep, go get another byte
  1445.          ;
  1446.          movea.l  (sp)+,a0                            ; restore registers
  1447.          rte                                          ; return
  1448.          ;
  1449.          ;        We've missed some data, so set overrun flag.
  1450.          ;
  1451. 50$      addq.b   #1,Overrun                          ; set overrun flag
  1452.          bra      20$                                 ; continue
  1453.          ;
  1454.          ;        Hit physical end of buffer, so wrap to the start of the buffer.
  1455.          ;
  1456. 60$      movea.l  i_BufPtr(pc),a0                     ; get buffer ptr
  1457.          bra.b    30$                                 ; continue
  1458.          ;
  1459.          ;        Hit buffer threshold, so tell other end not to send any more
  1460.          ;        data.
  1461.          ;
  1462. 70$      tst.b    Handshake                           ; are we handshaking?
  1463.          beq.b    40$                                 ; nope, skip RTS
  1464.          bset.b   #CIAB_COMRTS,_ciabpra               ; block further input
  1465.          bra.b    40$                                 ; go return
  1466.          ;
  1467.          ;
  1468.          ;
  1469. VBIntRtn:
  1470.          ;
  1471.          ;        If there's nothing in the buffer, there's no point in going
  1472.          ;        any further.
  1473.          ;
  1474.          move.l   i_InCnt(pc),d0                      ; anything in the buffer?
  1475.          bne.b    20$                                 ; yep, branch
  1476. 10$      lea.l    _custom,a0                          ; restore chip ptr
  1477.          moveq    #0,d0                               ; set Z flag
  1478.          rts                                          ; return
  1479.          ;
  1480.          ;        If we have been "disabled" then get out.
  1481.          ;
  1482. 20$      move.b   disableRead(pc),d0                  ; internally disabled?
  1483.          bge.b    10$                                 ; yep, get out of here
  1484.          lea.l    Start(pc),a5                        ; get base
  1485.          ;
  1486.          ;        If we have an active request, branch down to try and fulfill it.
  1487.          ;
  1488.          move.l   cr_IOReq(pc),d0                     ; get and test active I/O
  1489.          bne.b    30$                                 ; nzero, active, branch
  1490.          ;
  1491.          ;        Get first node in list and test if empty.
  1492.          ;
  1493.          move.l   (a1),a0                             ; get head of list
  1494.          move.l   (a0),d0                             ; get successor
  1495.          beq.b    10$                                 ; end of list? yep, branch
  1496.          ;
  1497.          ;        Remove the node from the list
  1498.          ;
  1499.          move.l   d0,(a1)                             ; make new head
  1500.          exg.l    d0,a0                               ; swap nodes
  1501.          move.l   a1,LN_PRED(a0)                      ; store predecessor
  1502.          ;
  1503.          ;        Setup fields for processing a read request
  1504.          ;
  1505.          movea.l  d0,a1                               ; get I/O request
  1506.          bclr.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; no longer queued
  1507.          bset.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; make it active
  1508.          move.l   a1,cr_IOReq-Start(a5)               ; store I/O request
  1509.          move.l   IO_DATA(a1),cr_OutPtr-Start(a5)     ; get/set output ptr
  1510.          move.l   IO_LENGTH(a1),cr_Length-Start(a5)   ; get/set output count
  1511.          ;
  1512.          ;        Process an active I/O request
  1513.          ;
  1514. 30$      movea.l  SysBase(pc),a6                      ; get ExecBase
  1515.          move.l   d0,a1                               ; get I/O request
  1516.          bsr      copyData                            ; go copy 'em
  1517.          tst.l    d0                                  ; done with request?
  1518.          beq.b    10$                                 ; nope, branch
  1519.          ;
  1520.          ;        the request has been satisfied, so return it.
  1521.          ;
  1522.          jsr      _LVOReplyMsg(a6)                    ; return I/O
  1523.          bra.b    10$
  1524.          ;
  1525.          ;        Registers:
  1526.          ;        Entry:   A1       Ptr to I/O Request
  1527.          ;                 A6       ExecBase
  1528.          ;        Exit:    D0       ZERO - request not done, do not reply it
  1529.          ;                          NZERO - request done, reply it
  1530.          ;
  1531. copyData:
  1532.          ;
  1533.          ;        Process an active I/O request (or fall through from above)
  1534.          ;
  1535.          movem.l  d2-d5/a1-a5,-(sp)                   ; save registers
  1536.          lea.l    Start(pc),a5                        ; get base
  1537.          movea.l  a1,a4                               ; get I/O request
  1538.          ;
  1539.          movea.l  i_BufOut(pc),a2                     ; get current bufout ptr
  1540.          movea.l  cr_OutPtr(pc),a3                    ; get current output ptr
  1541.          move.l   cr_Length(pc),d2                    ; get current bytes needed
  1542.          move.l   i_InCnt(pc),d3                      ; get current bytes in buffer
  1543.          ;
  1544.          ;        If we don't have enough bytes to satisfy the request,
  1545.          ;        set the length to the number of bytes we do have.
  1546.          ;
  1547.          cmp.l    d2,d3                               ; enuf to satisfy request?
  1548.          bge.b    15$                                 ; yep, so branch
  1549.          move.l   d3,d2                               ; # to copy = # in buffer
  1550.          bra.b    15$                                 ; branch to loop entry
  1551.          ;
  1552.          ;        Start of copy loop.
  1553.          ;
  1554. 10$      movea.l  i_BufPtr(pc),a2                     ; reset bufout to start
  1555.          ;
  1556.          ;        Entry point of copy loop.
  1557.          ;
  1558. 15$      move.l   d2,d3                               ; xfer # of bytes to copy
  1559.          ;
  1560.          ;        If the copy will extend past the end of the buffer, we can
  1561.          ;        only copy the number of bytes to the end this go around.
  1562.          ;
  1563.          move.l   i_BufEnd(pc),d0                     ; get ptr to end of buf
  1564.          sub.l    a2,d0                               ; calc # of bytes to end
  1565.          cmp.l    d0,d3                               ; # to copy < # to end?
  1566.          blt.b    20$                                 ; yep, branch
  1567.          move.l   d0,d3                               ; get bytes to end
  1568.          ;
  1569.          ;        Registers:
  1570.          ;
  1571.          ;        A2 = pointer from which data will be copied
  1572.          ;        A3 = pointer to which data will be copied
  1573.          ;        D2 = number of bytes that need to be copied
  1574.          ;        D3 = number of bytes to copy this iteration
  1575.          ;
  1576. 20$      btst.b   #SERB_EOFMODE,IO_SERFLAGS(a4)       ; EOFMODE requested?
  1577.          beq.b    30$                                 ; nope, just go copy
  1578.          ;
  1579.          ;        EOFMODE was specified so copy characters 1 at a time until
  1580.          ;        we hit an EOF character, the output butter has filled, or
  1581.          ;        the input buffer has drained.
  1582.          ;
  1583.          move.l   d3,d0                               ; get length
  1584.          ;
  1585. 21$      move.b   (a2)+,d1                            ; get byte
  1586.          move.b   d1,(a3)+                            ; put in output buffer
  1587.          ;
  1588.          lea.l    IO_TERMARRAY(a4),a1                 ; get termarry ptr
  1589.          cmp.b    (a1)+,d1                            ; found term char?
  1590.          bge.b    22$                                 ; possibly, branch
  1591.          cmp.b    (a1)+,d1                            ; found term char?
  1592.          bge.b    22$                                 ; possibly, branch
  1593.          cmp.b    (a1)+,d1                            ; found term char?
  1594.          bge.b    22$                                 ; possibly, branch
  1595.          cmp.b    (a1)+,d1                            ; found term char?
  1596.          bge.b    22$                                 ; possibly, branch
  1597.          cmp.b    (a1)+,d1                            ; found term char?
  1598.          bge.b    22$                                 ; possibly, branch
  1599.          cmp.b    (a1)+,d1                            ; found term char?
  1600.          bge.b    22$                                 ; possibly, branch
  1601.          cmp.b    (a1)+,d1                            ; found term char?
  1602.          bge.b    22$                                 ; possibly, branch
  1603.          cmp.b    (a1)+,d1                            ; found term char?
  1604.          bgt.b    23$                                 ; nope, branch
  1605. 22$      beq.b    24$                                 ; term char found?
  1606.          ;
  1607.          ;        Didn't find a term character, so continue with the copy loop
  1608.          ;
  1609. 23$      subq.l   #1,d0                               ; decr length counter
  1610.          bne.b    21$                                 ; continue if more
  1611.          bra.b    40$                                 ; done with copy, branch
  1612.          ;
  1613.          ;        We've found a termination character.
  1614.          ;
  1615. 24$      clr.l    cr_Length-Start(a5)                 ; done with request
  1616.          bra.b    50$                                 ; branch
  1617.          ;
  1618.          ;        EOFMODE not specified, so just do a bulk copy.
  1619.          ;
  1620.          ;        XXX POSSIBLE SPEEDUP XXX
  1621.          ;
  1622.          ;        For short copies it would be quicker to have a simple inline
  1623.          ;        loop, but what's short???  It would be different by CPU.
  1624.          ;
  1625. 30$      move.l   d3,d0                               ; get length
  1626.          movea.l  a3,a1                               ; where to put it
  1627.          movea.l  a2,a0                               ; where to get it
  1628.          jsr      _LVOCopyMem(a6)                     ; copy it
  1629.          adda.l   d3,a2                               ; update bufout
  1630.          adda.l   d3,a3                               ; update outptr
  1631.          ;
  1632.          ;        Fall through and entered from EOFMODE loop
  1633.          ;
  1634.          ;        If the following calculation results in a value greater than
  1635.          ;        zero, then we have a buffer wrap and need to process the
  1636.          ;        remaining bytes at the beginning of the buffer.
  1637.          ;
  1638. 40$      sub.l    d3,d2                               ; calc bytes left to copy
  1639.          bgt      10$                                 ; >0, more to copy, branch
  1640.          ;
  1641.          ;
  1642.          ;
  1643. 50$      move.l   a3,d1                               ; get outptr
  1644.          sub.l    cr_OutPtr(pc),d1                    ; calc length
  1645.          move.l   a3,cr_OutPtr-Start(a5)              ; update outptr
  1646.          ;
  1647.          ;        Update output ptr and bytes left in buffer
  1648.          ;
  1649.          move.l   a2,i_BufOut-Start(a5)               ; store bufout ptr
  1650.          sub.l    d1,i_InCnt-Start(a5)                ; calc bytes left in buffer
  1651.          add.l    d1,IO_ACTUAL(a4)                    ; update I/O request
  1652.          ;
  1653.          ;        If the threshold becomes positive here, then, if requested,
  1654.          ;        tell the other end that it's okay to start sending more data.
  1655.          ;
  1656.          add.l    d1,i_Thresh-Start(a5)               ; calc thresh and test
  1657.          ble.b    60$                                 ; <= 0, need more data, skip
  1658.          tst.b    Handshake-Start(a5)                 ; are we handshaking?
  1659.          beq.b    60$                                 ; nope, skip RTS
  1660.          btst.b   #CIAB_COMRTS,_ciabpra               ; currently stopped?
  1661.          beq.b    60$                                 ; nope, skip clear
  1662.          bclr.b   #CIAB_COMRTS,_ciabpra               ; ready to receive more data
  1663.          ;
  1664.          ;        Set error if we've had any overruns.
  1665.          ;
  1666. 60$      tst.b    Overrun-Start(a5)                   ; did overrun occur?
  1667.          beq.b    70$                                 ; nope, branch
  1668.          clr.b    Overrun-Start(a5)                   ; reset overrun flag
  1669.          move.b   #SerErr_LineErr,IO_ERROR(a4)        ; set error code
  1670.          ;
  1671.          ;        Calc number of bytes left to copy.  If the result is greater
  1672.          ;        than zero, then we have more to copy so return a "noreply"
  1673.          ;        status.
  1674.          ;
  1675. 70$      moveq    #0,d0                               ; assume noreply
  1676.          sub.l    d1,cr_Length-Start(a5)              ; update length and test
  1677.          bgt.b    90$                                 ; >0, more to do, branch
  1678.          ;
  1679.          ;        We've completed the I/O request either by copying the requested
  1680.          ;        of bytes or by finding an EOFMODE character, so return a "reply"
  1681.          ;        status.
  1682.          ;
  1683.          moveq    #1,d0                               ; indicate reply
  1684.          clr.l    cr_IOReq-Start(a5)                  ; clear request
  1685.          ;
  1686.          ;        Restore and exit
  1687.          ;
  1688. 90$      movem.l  (sp)+,d2-d5/a1-a5                   ; save registers
  1689.          rts                                          ; return (Reply status in D0)
  1690.          ;
  1691.          ;        Align data
  1692.          ;
  1693.          DS.L     0
  1694.          ;
  1695.          ;
  1696.          ;
  1697. Init:
  1698.          DC.L     sizeof_Base8n1
  1699.          DC.L     funcTab
  1700.          DC.L     dataTab
  1701.          DC.L     InitRoutine
  1702.          ;
  1703.          ;
  1704.          ;
  1705. funcTab:
  1706.          DC.W     -1
  1707.          DC.W     dev_Open-funcTab
  1708.          DC.W     dev_Close-funcTab
  1709.          DC.W     dev_Expunge-funcTab
  1710.          DC.W     dev_Null-funcTab
  1711.          DC.W     dev_BeginIO-funcTab
  1712.          DC.W     dev_AbortIO-funcTab
  1713.          DC.W     -1
  1714.          ;
  1715.          ;
  1716.          ;
  1717. dataTab:
  1718.          INITBYTE LN_TYPE,NT_DEVICE
  1719.          INITLONG LN_NAME,Name
  1720.          INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
  1721.          INITWORD LIB_VERSION,VERSION
  1722.          INITWORD LIB_REVISION,REVISION
  1723.          INITLONG LIB_IDSTRING,IdString
  1724.          DC.W     0
  1725.          ;
  1726.          ;        String Constants
  1727.          ;
  1728. miscresource:
  1729.          DC.B     "misc.resource",0
  1730. timerdevice:
  1731.          DC.B     "timer.device",0
  1732. intuitlib:
  1733.          DC.B     "intuition.library",0
  1734. Name:
  1735.          DC.B     "8n1.device",0
  1736. IdString:
  1737.          VSTRING
  1738.          ;
  1739.          ;        End of checksummed area.  (Realigns data too!)
  1740.          ;
  1741. ENDTag:
  1742.          DS.L     0
  1743.          ;
  1744.          ;        Global SysBase (Use instead of AbsExecBase for speed)
  1745.          ;
  1746. SysBase:
  1747.          DC.L     0
  1748.          ;
  1749.          ;        Internal buffer tracking (DO NOT CHANGE THE ORDER!!!!)
  1750.          ;
  1751. i_BufPtr:
  1752.          DC.L     0
  1753. i_BufIn:
  1754.          DC.L     0
  1755. i_BufOut:
  1756.          DC.L     0
  1757. i_BufEnd:
  1758.          DC.L     0
  1759. i_InCnt:
  1760.          DC.L     0
  1761. i_Thresh:
  1762.          DC.L     0
  1763.          ;
  1764.          ;        Used while processing a read request.
  1765.          ;
  1766. cr_IOReq:
  1767.          DC.L     0
  1768. cr_OutPtr:
  1769.          DC.L     0
  1770. cr_Length:
  1771.          DC.L     0
  1772.          ;
  1773.          ;        List head for read requests
  1774.          ;
  1775. readQ:
  1776.          DC.L     readQ+MLH_TAIL
  1777.          DC.L     0
  1778.          DC.L     readQ
  1779.          ;
  1780.          ;        Write control.
  1781.          ;
  1782. cw_Length:
  1783.          DC.L     0
  1784. cw_Buffer:
  1785.          DC.L     0
  1786. cw_IOReq:
  1787.          DC.L     0
  1788.          ;
  1789.          ;        List head for write requests
  1790.          ;
  1791. writeQ:
  1792.          DC.L     writeQ+MLH_TAIL
  1793.          DC.L     0
  1794.          DC.L     writeQ
  1795.          ;
  1796.          ;
  1797.          ;
  1798. timerPort:
  1799.          DC.L     0                                   ; LN_SUCC
  1800.          DC.L     0                                   ; LN_PRED
  1801.          DC.B     NT_MSGPORT                          ; LN_TYPE
  1802.          DC.B     0                                   ; LN_PRI
  1803.          DC.L     0                                   ; LN_NAME
  1804.          DC.B     3                                   ; MP_FLAGS (undoc'ed)
  1805.          DC.B     0                                   ; MP_SIGBIT
  1806.          DC.L     timerRtn                            ; MP_SIGTASK
  1807.          DC.L     timerPort+MP_MSGLIST+LH_TAIL        ; LH_HEAD
  1808.          DC.L     0                                   ; LH_TAIL
  1809.          DC.L     timerPort+MP_MSGLIST                ; LH_TAILPRED
  1810.          DC.B     0                                   ; LH_TYPE
  1811.          DC.B     0                                   ; LH_pad
  1812.          DC.W     0                                   ; long align
  1813.          ;
  1814.          ;
  1815.          ;
  1816. timerReq:
  1817.          DC.L     0                                   ; LN_SUCC
  1818.          DC.L     0                                   ; LN_PRED
  1819.          DC.B     NT_MESSAGE                          ; LN_TYPE
  1820.          DC.B     0                                   ; LN_PRI
  1821.          DC.L     0                                   ; LN_NAME
  1822.          DC.L     timerPort                           ; MN_REPLYPORT
  1823.          DC.W     IOTV_SIZE                           ; MN_LENGTH
  1824.          DC.L     0                                   ; IO_DEVICE
  1825.          DC.L     0                                   ; IO_UNIT
  1826.          DC.W     TR_ADDREQUEST                       ; IO_COMMAND
  1827.          DC.B     0                                   ; IO_FLAGS
  1828.          DC.B     0                                   ; IO_ERROR
  1829.          DC.L     0                                   ; TV_SECS
  1830.          DC.L     0                                   ; TV_MICROS
  1831.          ;
  1832.          ;
  1833.          ;
  1834. VBInterrupt:
  1835.          DC.L     0                                   ; LN_SUCC
  1836.          DC.L     0                                   ; LN_PRED
  1837.          DC.B     NT_INTERRUPT                        ; LN_TYPE
  1838.          DC.B     127                                 ; LN_PRI
  1839.          DC.L     Name                                ; LN_NAME
  1840.          DC.L     readQ                               ; IS_DATA
  1841.          DC.L     VBIntRtn                            ; IS_CODE
  1842.          ;
  1843.          ;        Global flags
  1844.          ;
  1845. Overrun:
  1846.          DC.B     0
  1847. Handshake:
  1848.          DC.B     0
  1849. disableRead:
  1850.          DC.B     -1
  1851.          ;
  1852.          ;
  1853.          ;
  1854.          END
  1855.  
  1856.